package com.duobaoyu.dby.supply.biz.client.resource.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.core.constant.SecurityConstants;
import com.duobaoyu.dby.common.core.constant.ServiceNameConstants;
import com.duobaoyu.dby.common.core.constant.enums.ProductInfoEnum;
import com.duobaoyu.dby.common.core.util.ExceptionUtils;
import com.duobaoyu.dby.common.core.util.R;
import com.duobaoyu.dby.common.mybatis.util.EnumUtils;
import com.duobaoyu.dby.resource.admin.feign.RemoteResourceTaskAsyncAdminService;
import com.duobaoyu.dby.resource.remote.common.dto.config.TaskAsyncDTO;
import com.duobaoyu.dby.resource.remote.common.dto.config.TaskAsyncQueryPageDTO;
import com.duobaoyu.dby.resource.remote.common.dto.config.TaskAsyncStatusDTO;
import com.duobaoyu.dby.resource.remote.common.enums.BizTypeEnum;
import com.duobaoyu.dby.resource.remote.common.enums.TaskStatusEnum;
import com.duobaoyu.dby.resource.remote.common.to.config.TaskAsyncTO;
import com.duobaoyu.dby.supply.biz.client.resource.ResourceTaskAsyncAdminClient;
import com.duobaoyu.dby.supply.biz.client.resource.bean.dto.TaskAsyncQueryDTO;
import com.duobaoyu.dby.supply.biz.client.resource.bean.vo.TaskExportVO;
import com.duobaoyu.dby.supply.biz.client.resource.converter.ResourceConverter;
import com.duobaoyu.dby.supply.biz.util.RemoteResultCheckUtil;
import com.duobaoyu.dby.supply.core.common.exception.CustomException;
import com.duobaoyu.dby.supply.core.task.AbstractTaskStrategy;
import com.duobaoyu.dby.supply.core.task.bean.TaskAsyncParam;
import com.duobaoyu.dby.supply.core.task.bean.TaskAsyncResultTO;
import com.duobaoyu.dby.supply.core.task.bean.exporttask.ExcelHeader;
import com.duobaoyu.dby.supply.core.task.bean.exporttask.ExportParam;
import com.duobaoyu.dby.supply.core.task.bean.exporttask.TaskExport;
import com.duobaoyu.dby.supply.core.task.constants.ExcelConstants;
import com.duobaoyu.dby.supply.core.task.enums.BizTaskTypeEnum;
import com.duobaoyu.dby.supply.core.task.enums.TaskTypeEnum;
import com.duobaoyu.dby.supply.core.task.service.TaskAsyncService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName ResourceTaskAsyncAdminClientImpl
 * @createTime 15:20:00 2023/10/08
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ResourceTaskAsyncAdminClientImpl implements ResourceTaskAsyncAdminClient {

    private final TaskAsyncService taskAsyncService;
    private final ResourceConverter resourceConverter;
    private final RemoteResourceTaskAsyncAdminService remoteResourceTaskAsyncAdminService;

    @Override
    public void asyncTaskHandler(Long taskId) {
        R<TaskAsyncTO> result = remoteResourceTaskAsyncAdminService.queryTaskAsync(taskId, SecurityConstants.FROM_IN);
		RemoteResultCheckUtil.checkRemoteResult(result, ServiceNameConstants.RESOURCE_SERVICE, taskId);

        TaskAsyncTO taskAsync = result.getData();
        if (Objects.isNull(taskAsync)) {
            if(log.isDebugEnabled()) {
                log.debug("未查询到异步任务信息 taskId : {}",taskId);
            }
            return;
        }

        AbstractTaskStrategy abstractTaskStrategy = taskAsyncService.taskAsyncService(taskAsync.getTaskType(), taskAsync.getBizTaskType());
        TaskAsyncStatusDTO taskAsyncStatus = new TaskAsyncStatusDTO();
        taskAsyncStatus.setTaskId(taskAsync.getId());
        try {
            TaskAsyncParam asyncParam = JSON.parseObject(taskAsync.getTaskParam(), TaskAsyncParam.class);
            asyncParam.setTaskId(taskId);
            if (Objects.nonNull(asyncParam.getIzSplit()) && asyncParam.getIzSplit()) {
                abstractTaskStrategy.splitTaskHandler(asyncParam);
                return;
            }
            TaskAsyncResultTO asyncResult = (TaskAsyncResultTO) abstractTaskStrategy.taskAsyncHandler(asyncParam);
            taskAsyncStatus.setTaskStatus(TaskStatusEnum.COMPLETE.getValue());
            if(Objects.nonNull(asyncResult)) {
                taskAsyncStatus.setTaskResult(JSON.toJSONString(asyncResult));
                Optional.ofNullable(asyncResult.getSuccessTaskCount()).ifPresent(taskAsyncStatus::setSuccessTaskCount);
                Optional.ofNullable(asyncResult.getFailTaskCount()).ifPresent(taskAsyncStatus::setFailTaskCount);
                if (Objects.nonNull(asyncResult.getSuccessTaskCount()) && Objects.nonNull(asyncResult.getFailTaskCount())) {
                    taskAsyncStatus.setImportTaskCount(asyncResult.getSuccessTaskCount() + asyncResult.getFailTaskCount());
                }
            }
        } catch (Exception e) {
            taskAsyncStatus.setTaskStatus(TaskStatusEnum.FAIL.getValue());
            taskAsyncStatus.setFailTaskCount(Optional.ofNullable(taskAsync).map(TaskAsyncTO::getImportTaskCount).orElse(CommonConstants.ZERO));
            taskAsyncStatus.setTaskReason(ExceptionUtils.getExceptionMsg(e, CommonConstants.HUNDRED * CommonConstants.TEN));
        }
        remoteResourceTaskAsyncAdminService.updateTaskAsyncStatus(taskAsyncStatus, SecurityConstants.FROM_IN);
    }

    @Override
    public List<ExcelHeader> queryExcelHeader(String bizTaskType) {
        R<List<ExcelHeader>> result = remoteResourceTaskAsyncAdminService.queryExcelHeader(bizTaskType, SecurityConstants.FROM_IN);
        RemoteResultCheckUtil.checkRemoteResult(result, ServiceNameConstants.RESOURCE_SERVICE, bizTaskType);
        return result.getData();
    }

	@Override
	public void asyncExport(ExportParam<String> exportParam) {
		BizTaskTypeEnum bizTaskTypeEnum = Optional.ofNullable(BizTaskTypeEnum.getBizTaskTypeEnum(exportParam.getExportDataType())).orElseThrow(() -> new CustomException("不存在的导出数据类型"));
		TaskExport taskExport = TaskExport.builder()
				.searchParameter(exportParam.getSearchParameter())
				.exportedFieldsParameter(exportParam.getExportedFieldsParameter())
				.sheetName(bizTaskTypeEnum.getDescribe())
				.maxExportCount(ExcelConstants.FIFTY_THOUSAND_COUNT)
				.productInfoEnum(ProductInfoEnum.SUPPLY)
				.pageSize(ExcelConstants.EXPORT_BATCH_COUNT)
				.build();
		TaskAsyncParam taskAsyncParam = TaskAsyncParam.builder().taskParam(JSON.toJSONString(taskExport)).build();
		taskAsyncParam.setBizType(BizTypeEnum.NEW_SUPPLY_CHAIN.getValue());
		taskAsyncParam.setBizTaskType(bizTaskTypeEnum.getValue());
		TaskAsyncDTO taskAsync = TaskAsyncDTO.builder()
				.bizType(BizTypeEnum.NEW_SUPPLY_CHAIN.getValue())
				.bizTaskType(bizTaskTypeEnum.getValue())
				.taskType(TaskTypeEnum.EXPORT_TASK.getValue())
				.taskParam(JSON.toJSONString(taskAsyncParam))
				.build();
		R<TaskAsyncTO> result = remoteResourceTaskAsyncAdminService.createTaskAsync(taskAsync, SecurityConstants.FROM_IN);
		RemoteResultCheckUtil.checkRemoteResult(result, ServiceNameConstants.RESOURCE_SERVICE, taskAsync);
	}

    @Override
    public Page<TaskExportVO> queryTaskExportAsyncPage(TaskAsyncQueryDTO taskAsyncQuery) {
        TaskAsyncQueryPageDTO dto = resourceConverter.toTaskAsyncQueryPage(taskAsyncQuery);
        if(EnumUtils.eq(BizTypeEnum.SUPPLY_CHAIN,taskAsyncQuery.getBizType())) {
			dto.setBizType(BizTypeEnum.NEW_SUPPLY_CHAIN.getValue());
		}
        R<Page<TaskAsyncTO>> result = remoteResourceTaskAsyncAdminService.queryTaskAsyncPage(dto, SecurityConstants.FROM_IN);
        RemoteResultCheckUtil.checkRemoteResult(result, ServiceNameConstants.RESOURCE_SERVICE, taskAsyncQuery);
        return resourceConverter.toTaskExportPage(result.getData());
    }
}
